<?php
/**
 * Created by PhpStorm.
 * User: jaylen
 * Date: 2020-05-28
 * Time: 14:35
 */

namespace app\admin\model;


use app\admin\model\traits\ModelTableTraits;
use app\common\exception\HaveUseException;
use app\common\exception\ParameterException;
use app\common\model\BaseModel;
use app\common\validate\IDCollection;
use app\common\validate\IDMustBeRequire;
use think\facade\Db;
use think\facade\Env;
use think\model\concern\SoftDelete;
use app\admin\validate\ModelTable as Validate;
use app\admin\model\ModelFields as ModelFieldsModel;
use app\common\model\Content as ContentModel;

class ModelTable extends BaseModel
{
    protected $hidden = ['create_time','update_time','delete_time'];

    use SoftDelete;
    protected $deleteTime = 'delete_time';

    protected $database = null;
    protected $database_prefix = null;

    use ModelTableTraits;

    public function __construct(array $data = [])
    {
        parent::__construct($data);

        $this->database = Env::get('database.database');
        $this->database_prefix = Env::get('database.prefix');
    }

    public function modelFields()
    {
        return $this->hasMany('ModelFields','model_id','id');
    }

    /**
     * 获取模型的分页数据
     * @param array $params
     * @return \think\Paginator
     */
    public static function getPaginationList(array $params)
    {
        static::validatePaginationData($params);

        $static = new static();

        foreach ($params as $name => $value) {
            $value = trim($value);
            switch ($name) {
                case 'cn_name':
                    if (!empty($value)) {
                        $like_text = '%' . $value . '%';
                        $static = $static->whereLike('cn_name', $like_text);
                    }
                    break;
            }
        }

        return $static
            ->paginate([
                'page' => $params['page'],
                'list_rows' => $params['limit']
            ], false);
    }

    /**
     * 根据id获取模型的相关数据
     * @param $id
     * @return array
     */
    public static function getModelTableByID($id)
    {
        $validate = new IDMustBeRequire();
        if (!$validate->check(['id'=>$id])) {
            throw new ParameterException([
                'msg' => $validate->getError(),
            ]);
        }

        $result = static::with(['modelFields'])
            ->find($id);

        if (!$result) {
            return [];
        } else {
            $data = $result->hidden(['modelFields'=>['model_id','sort','status']])->toArray();

            $data['fields_data'] = array_reduce($data['modelFields'], function ($v, $item) {
                if (in_array($item['type'], [2,3,4])) {
                    $item['values'] = implode(',',$item['values']);
                }
                $v[] = $item;
                return $v;
            }, []);
            unset($data['modelFields']);
            return $data;
        }
    }

    /**
     * 获取全部模型的名称
     * @return array
     */
    public static function getAllModelTableName()
    {
        $data = static::getDataWithField([['status','=',1]],['id','cn_name','en_name']);

        return $data->isEmpty() ? [] : $data->toArray();
    }

    /**
     * 根据id获取模型表名称
     * @param $id
     * @return mixed|string
     */
    public static function getTableEnNameByID($id)
    {
        if (empty($id)) {
            return '';
        }

        $data = static::field(['en_name'])->find($id);

        return $data ? $data->en_name : '';
    }

    /**
     * 获取模型字段数据
     * @param array $params
     * @return array
     */
    public static function getFieldsData(array $params)
    {
        if (!isset($params['id']) || empty($params['id'])) {
            return [];
        }

        $model_data = static::with(['modelFields' => function($query) {
            $query->field(['cn_name','en_name','values','tips','type','model_id'])
                ->order(['sort' => 'asc']);
        }])
            ->where('id','=', $params['id'])
            ->find();

        if (!$model_data || !isset($model_data['modelFields']) || empty($model_data['modelFields'])) {
            return [];
        }

        $model_data = $model_data->toArray();

        if (isset($params['table_id']) && !empty($params['table_id'])) {
            return static::recombinantFieldsData($model_data['modelFields'], $model_data['en_name'], $params['table_id']);
        } else {
            return static::recombinantFieldsData($model_data['modelFields']);
        }
    }

    /**
     * 添加模型信息
     * @param array $data
     * @return bool
     */
    public static function addModelTable(array $data)
    {
        $validate = new Validate();
        if (!$validate->scene('add')->check($data)) {
            throw new ParameterException([
                'msg' => $validate->getError(),
            ]);
        }

        $static = new static;

        $static->startTrans();

        self::handleSubmitModelTableData($data);

        try {
            // 写入数据到对应的数据表中
            $static->allowField(['en_name','cn_name','status'])
                ->save($data);
            $static = $static->refresh();
            $static->modelFields()->saveAll($data['fields_data']);

            // 创建对应的数据表
            $static->createModelTable($data);

            $static->commit();
        } catch (\Exception $e) {
            $static->rollback();
            return false;
        }

        return true;
    }

    /**
     * 编辑模型信息
     * @param array $data
     * @return bool
     */
    public static function editModelTable(array $data)
    {
        $validate = new Validate();
        if (!$validate->scene('edit')->check($data)) {
            throw new ParameterException([
                'msg' => $validate->getError(),
            ]);
        }

        $static = static::find($data['id']);
        $static->startTrans();

        self::handleSubmitModelTableData($data);
        $diffData = $static->getDiffModelFieldsData($data['fields_data']);
        $needDeleteImage = []; // 保存需要删除的图片信息

        try {
            // 更新模型表的相关数据
            $needDeleteImage = $static->changeModelFields($static->en_name, $diffData['change_field']);
            $needDeleteImage = array_merge($needDeleteImage, $static->delModelFields($static->en_name, $diffData['delete_field']));
            $static->addModelFields($static->en_name, $diffData['add_field']);

            if ($data['en_name'] != $static->en_name) {
                $sql = "RENAME TABLE `{$static->database}`.`{$static->database_prefix}{$static->en_name}` TO `{$static->database}`.`{$static->database_prefix}{$data['en_name']}`";
                Db::execute($sql);
            }

            // 先删除旧数据再添加
            ModelFieldsModel::destroy(['model_id'=>$data['id']],true);  // 使用真实删除

            // 写入数据到对应的数据表中
            $static->allowField(['en_name','cn_name','status'])
                ->save($data);
            $static = $static->refresh();
            $static->modelFields()->saveAll($data['fields_data']);

            $static->commit();
        } catch (\Exception $e) {
            $static->rollback();
            return false;
        }

        if (!empty($needDeleteImage)) {
            delFile($needDeleteImage);
        }

        return true;
    }

    /**
     * 删除模型数据
     * @param $ids
     * @return bool
     */
    public static function delModelTable($ids)
    {
        $validate = new IDCollection();
        if (!$validate->check([
            'ids' => $ids
        ])) {
            throw new ParameterException([
                'msg' => $validate->getError()
            ]);
        }

        //判断是否为数组，然后将字符串转为数组
        if (!is_array($ids)){
            $ids = explode(',',$ids);
        }

        // 先验证有无内容使用了该模型
        $content = ContentModel::where([['model_id','in',$ids]])->column('id');

        if (!empty($content)) {
            throw new HaveUseException([
                'msg' => '还有内容使用了该模型'
            ]);
        }

        if (static::destroy($ids) !== false) {
            return true;
        } else {
            return false;
        }
    }
}